package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.OmcMedicRecordMapper;
import com.csun.cmny.provider.exceptions.OmcBizException;
import com.csun.cmny.provider.model.constant.MedicConstant;
import com.csun.cmny.provider.model.domain.OmcMedicPlan;
import com.csun.cmny.provider.model.domain.OmcMedicRecord;
import com.csun.cmny.provider.model.domain.OmcNursingUserBind;
import com.csun.cmny.provider.model.domain.OmcOrder;
import com.csun.cmny.provider.model.dto.medic.MedicRecordConfirmDto;
import com.csun.cmny.provider.model.dto.medic.MedicRecordFeedDto;
import com.csun.cmny.provider.model.dto.medic.MedicRecordQueryDto;
import com.csun.cmny.provider.model.dto.medic.MedicRecordTimeOutDto;
import com.csun.cmny.provider.model.vo.MedicRecordVo;
import com.csun.cmny.provider.service.OmcActivitiService;
import com.csun.cmny.provider.service.OmcMedicPlanService;
import com.csun.cmny.provider.service.OmcMedicRecordService;
import com.csun.cmny.provider.service.OmcNursingUserBindService;
import com.csun.cmny.util.DateUtil;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-08-13 15:11
 * @Description: the class omc medic record service impl
 */
@Slf4j
@Service
@Transactional
public class OmcMedicRecordServiceImpl extends BaseService<OmcMedicRecord>
        implements OmcMedicRecordService {

    @Resource
    private TaskService taskService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private HistoryService historyService;
    @Resource
    private OmcActivitiService omcActivitiService;
    @Resource
    private OmcMedicRecordMapper omcMedicRecordMapper;
    @Resource
    private OmcMedicPlanService omcMedicPlanService;
    @Resource
    private OmcNursingUserBindService omcNursingUserBindService;

    /**
     * query medic record list with page
     *
     * @param medicRecordQueryDto the medic record query dto
     * @return the list.
     */
    @Override
    public List<MedicRecordVo> queryListWithPage(MedicRecordQueryDto medicRecordQueryDto) {

        PageHelper.startPage(medicRecordQueryDto.getPageNum(), medicRecordQueryDto.getPageSize());

        return omcMedicRecordMapper.queryListWithPage(medicRecordQueryDto);
    }

    /**
     * medic record feed
     *
     * @param medicRecordFeedDto the medic record feed dto
     * @param loginAuthDto       the login auth dto
     * @return the int.
     */
    @Override
    public Integer feed(MedicRecordFeedDto medicRecordFeedDto, LoginAuthDto loginAuthDto) {

        Long medicRecordId = medicRecordFeedDto.getId();
        Long userId = loginAuthDto.getUserId();

        // 根据用户查询所在班组
        OmcNursingUserBind omcNursingUserBind = new OmcNursingUserBind();
        omcNursingUserBind.setUserId(userId);
        omcNursingUserBind = omcNursingUserBindService.selectOne(omcNursingUserBind);
        if (omcNursingUserBind == null) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038008);
        }

        Long nursingGroupId = omcNursingUserBind.getNursingGroupId();

        OmcMedicRecord omcMedicRecordQuery = omcMedicRecordMapper.selectByPrimaryKey(medicRecordId);
        if (omcMedicRecordQuery == null) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038009);
        }

        // 判断是否为该班组任务
        if (!nursingGroupId.equals(omcMedicRecordQuery.getNursingGroupId())) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038010);
        }

        String processInstanceId = omcMedicRecordQuery.getProcessInstanceId();

        Task task = taskService.createTaskQuery()
                .taskTenantId(loginAuthDto.getGroupId().toString())
                .processDefinitionKey(MedicConstant.PROCESS_KEY_MEDIC_RECORD)
                .taskCandidateGroup(nursingGroupId.toString())
                .processInstanceId(processInstanceId)
                .taskDefinitionKey(MedicConstant.MEDIC_RECORD_TASK_FEED)
                .singleResult();

        if (task == null) {
            // 任务不存在
            throw new OmcBizException(ErrorCodeEnum.OMC10038003);
        }

        String comment = MedicConstant.MEDIC_RECORD_COMMENT_FEED;
        Integer state = MedicConstant.MEDIC_RECORD_STATE_FEED;

        OmcMedicRecord omcMedicRecord = new OmcMedicRecord();
        omcMedicRecord.setId(medicRecordId);
        omcMedicRecord.setState(state);
        omcMedicRecord.setUpdateInfo(loginAuthDto);

        Integer result = omcMedicRecordMapper.updateByPrimaryKeySelective(omcMedicRecord);
        if (result < 1) {
            return result;
        }


        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put(MedicConstant.VAR_MEDIC_RECORD_NURSING, userId.toString());

        // 设置用户id
        Authentication.setAuthenticatedUserId(loginAuthDto.getUserName() + "[护工]");
        // 添加批注信息
        taskService.addComment(task.getId(), processInstanceId, comment);
        // 完成任务
        taskService.complete(task.getId(), variables);

        return result;
    }

    /**
     * medic record nursing confirm
     *
     * @param medicRecordConfirmDto the medic record config dto
     * @param loginAuthDto          the login auth dto
     * @return the int.
     */
    @Override
    public Integer nursingConfirm(MedicRecordConfirmDto medicRecordConfirmDto, LoginAuthDto loginAuthDto) {

        Long medicRecordId = medicRecordConfirmDto.getId();
        Long userId = loginAuthDto.getUserId();

        // 根据用户查询所在班组
        OmcNursingUserBind omcNursingUserBind = new OmcNursingUserBind();
        omcNursingUserBind.setUserId(userId);
        omcNursingUserBind = omcNursingUserBindService.selectOne(omcNursingUserBind);
        if (omcNursingUserBind == null) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038008);
        }

        Long nursingGroupId = omcNursingUserBind.getNursingGroupId();

        OmcMedicRecord omcMedicRecordQuery = omcMedicRecordMapper.selectByPrimaryKey(medicRecordId);
        if (omcMedicRecordQuery == null) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038009);
        }

        // 判断是否为该班组任务
        if (!nursingGroupId.equals(omcMedicRecordQuery.getNursingGroupId())) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038010);
        }

        String processInstanceId = omcMedicRecordQuery.getProcessInstanceId();

        Task task = taskService.createTaskQuery()
                .taskTenantId(loginAuthDto.getGroupId().toString())
                .processDefinitionKey(MedicConstant.PROCESS_KEY_MEDIC_RECORD)
                .taskAssignee(userId.toString())
                .processInstanceId(processInstanceId)
                .taskDefinitionKey(MedicConstant.MEDIC_RECORD_TASK_NURSING_CONFIRM)
                .singleResult();

        if (task == null) {
            // 任务不存在
            throw new OmcBizException(ErrorCodeEnum.OMC10038003);
        }

        String comment = MedicConstant.MEDIC_RECORD_COMMENT_NURSING_CONFIRM;
        Integer state = MedicConstant.MEDIC_RECORD_STATE_NURSING_CONFIRM;

        OmcMedicRecord omcMedicRecord = new OmcMedicRecord();
        omcMedicRecord.setId(medicRecordId);
        omcMedicRecord.setState(state);
        omcMedicRecord.setRecordTime(DateUtil.dateToString(new Date()));
        omcMedicRecord.setUpdateInfo(loginAuthDto);

        Integer result = omcMedicRecordMapper.updateByPrimaryKeySelective(omcMedicRecord);
        if (result < 1) {
            return result;
        }

        // 设置用户id
        Authentication.setAuthenticatedUserId(loginAuthDto.getUserName() + "[护工]");
        // 添加批注信息
        taskService.addComment(task.getId(), processInstanceId, comment);
        // 完成任务
        taskService.complete(task.getId());

        return result;
    }

    /**
     * medic record monitor confirm
     *
     * @param medicRecordConfirmDto the medic record confirm dto
     * @param loginAuthDto          the login auth dto
     * @return the int.
     */
    @Override
    public Integer monitorConfirm(MedicRecordConfirmDto medicRecordConfirmDto, LoginAuthDto loginAuthDto) {

        Long medicRecordId = medicRecordConfirmDto.getId();
        Long userId = loginAuthDto.getUserId();

        // 根据用户查询所在班组
        OmcNursingUserBind omcNursingUserBind = new OmcNursingUserBind();
        omcNursingUserBind.setUserId(userId);
        omcNursingUserBind = omcNursingUserBindService.selectOne(omcNursingUserBind);
        if (omcNursingUserBind == null) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038008);
        }

        Long nursingGroupId = omcNursingUserBind.getNursingGroupId();

        OmcMedicRecord omcMedicRecordQuery = omcMedicRecordMapper.selectByPrimaryKey(medicRecordId);
        if (omcMedicRecordQuery == null) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038009);
        }

        // 判断是否为该班组任务
        if (!nursingGroupId.equals(omcMedicRecordQuery.getNursingGroupId())) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038010);
        }

        String processInstanceId = omcMedicRecordQuery.getProcessInstanceId();

        Task task = taskService.createTaskQuery()
                .taskTenantId(loginAuthDto.getGroupId().toString())
                .processDefinitionKey(MedicConstant.PROCESS_KEY_MEDIC_RECORD)
                .taskAssignee(userId.toString())
                .processInstanceId(processInstanceId)
                .taskDefinitionKey(MedicConstant.MEDIC_RECORD_TASK_MONITOR_CONFIRM)
                .singleResult();

        if (task == null) {
            // 任务不存在
            throw new OmcBizException(ErrorCodeEnum.OMC10038003);
        }

        String comment = MedicConstant.MEDIC_RECORD_COMMENT_MONITOR_CONFIRM;
        Integer state = MedicConstant.MEDIC_RECORD_STATE_MONITOR_CONFIRM;

        OmcMedicRecord omcMedicRecord = new OmcMedicRecord();
        omcMedicRecord.setId(medicRecordId);
        omcMedicRecord.setState(state);
        omcMedicRecord.setUpdateInfo(loginAuthDto);

        Integer result = omcMedicRecordMapper.updateByPrimaryKeySelective(omcMedicRecord);
        if (result < 1) {
            return result;
        }

        // 设置用户id
        Authentication.setAuthenticatedUserId(loginAuthDto.getUserName() + "[班长]");
        // 添加批注信息
        taskService.addComment(task.getId(), processInstanceId, comment);
        // 完成任务
        taskService.complete(task.getId());

        return result;
    }

    /**
     * medic record medic record time out dto
     *
     * @param medicRecordTimeOutDto the medic record time out dto
     * @param loginAuthDto          the login auth dto
     * @return the int.
     */
    @Override
    public Integer timeOut(MedicRecordTimeOutDto medicRecordTimeOutDto, LoginAuthDto loginAuthDto) {

        Long medicRecordId = medicRecordTimeOutDto.getId();
        Long userId = loginAuthDto.getUserId();

        // 根据用户查询所在班组
        OmcNursingUserBind omcNursingUserBind = new OmcNursingUserBind();
        omcNursingUserBind.setUserId(userId);
        omcNursingUserBind = omcNursingUserBindService.selectOne(omcNursingUserBind);
        if (omcNursingUserBind == null) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038008);
        }

        Long nursingGroupId = omcNursingUserBind.getNursingGroupId();

        OmcMedicRecord omcMedicRecordQuery = omcMedicRecordMapper.selectByPrimaryKey(medicRecordId);
        if (omcMedicRecordQuery == null) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038009);
        }

        // 判断是否为该班组任务
        if (!nursingGroupId.equals(omcMedicRecordQuery.getNursingGroupId())) {
            throw new OmcBizException(ErrorCodeEnum.OMC10038010);
        }

        String processInstanceId = omcMedicRecordQuery.getProcessInstanceId();

        Task task = taskService.createTaskQuery()
                .taskTenantId(loginAuthDto.getGroupId().toString())
                .processDefinitionKey(MedicConstant.PROCESS_KEY_MEDIC_RECORD)
                .taskAssignee(userId.toString())
                .processInstanceId(processInstanceId)
                .taskDefinitionKey(MedicConstant.MEDIC_RECORD_TASK_TIME_OUT)
                .singleResult();

        if (task == null) {
            // 任务不存在
            throw new OmcBizException(ErrorCodeEnum.OMC10038003);
        }

        int state = omcMedicRecordQuery.getState();
        String comment = medicRecordTimeOutDto.getComment();
        switch (state) {
            case MedicConstant.MEDIC_RECORD_STATE_DELAY_FEED :
                comment = MedicConstant.MEDIC_RECORD_COMMENT_FEED_DELAY_SIGN;
                break;
            case MedicConstant.MEDIC_RECORD_STATE_DELAY_NURSING_CONFIRM :
                comment = MedicConstant.MEDIC_RECORD_COMMENT_NURSING_CONFIRM_DELAY_SIGN;
                break;
            case MedicConstant.MEDIC_RECORD_STATE_DELAY_MONITOR_CONFIRM :
                comment = MedicConstant.MEDIC_RECORD_COMMENT_MONITOR_CONFIRM_DELAY_SIGN;
                break;
        }

        state = MedicConstant.MEDIC_RECORD_STATE_TIME_OUT;

        OmcMedicRecord omcMedicRecord = new OmcMedicRecord();
        omcMedicRecord.setId(medicRecordId);
        omcMedicRecord.setState(state);
        omcMedicRecord.setComment(medicRecordTimeOutDto.getComment()); // 批注
        omcMedicRecord.setUpdateInfo(loginAuthDto);

        Integer result = omcMedicRecordMapper.updateByPrimaryKeySelective(omcMedicRecord);
        if (result < 1) {
            return result;
        }

        // 设置用户id
        Authentication.setAuthenticatedUserId(loginAuthDto.getUserName() + "[班长]");
        // 添加批注信息
        taskService.addComment(task.getId(), processInstanceId, comment);
        // 完成任务
        taskService.complete(task.getId());

        return result;
    }

    /**
     * medic record apply
     *
     * @param param        the param
     * @param loginAuthDto the login auth dto
     * @return the int.
     */
    @Override
    public Integer apply(Map<String, Object> param, LoginAuthDto loginAuthDto) {

        // String startMedic = date + "T" + str_start_hour + ":" + "00" + ":" + "05";
        // String endMedic = date + "T" + str_end_hour + ":" + "00" + ":"  + "00";
        String startMedic = param.get("startMedic").toString();
        String endMedic = param.get("endMedic").toString();
        Long medicPlanId = Long.valueOf(param.get("medicPlanId") + "");
        String date = param.get("date").toString();
        log.info("# start medic = {}, end medic = {}", startMedic, endMedic);

        OmcMedicPlan omcMedicPlanQuery = omcMedicPlanService.selectByKey(medicPlanId);

        OmcMedicRecord omcMedicRecord = new OmcMedicRecord();
        omcMedicRecord.setMedicPlanId(medicPlanId);
        omcMedicRecord.setDate(date);
        //omcMedicRecord.setTimeSlice(str_start_hour + ":" + "00" + ":" + "00 -- " + str_end_hour + ":" + "00" + ":"  + "00");
        omcMedicRecord.setTimeSlice("2019-08-15 -- 2019-08-16");
        omcMedicRecord.setUserName(loginAuthDto.getUserName());
        omcMedicRecord.setGroupId(loginAuthDto.getGroupId());
        omcMedicRecord.setNursingGroupId(omcMedicPlanQuery.getNursingGroupId());

        // 调用子流程  -- 用药记录流程
        // 启动请假申请流程
        Map<String,Object> recordVariables = new HashMap<String,Object>();
        recordVariables.put(MedicConstant.VAR_MEDIC_RECORD_START_MEDIC, startMedic);
        recordVariables.put(MedicConstant.VAR_MEDIC_RECORD_END_MEDIC, endMedic);
        recordVariables.put(MedicConstant.VAR_MEDIC_RECORD_NURSING_GROUP_ID, "" + omcMedicPlanQuery.getNursingGroupId().toString());
        recordVariables.put(MedicConstant.VAR_MEDIC_RECORD_MONITOR, "" + loginAuthDto.getUserId().toString());

        // 启动流程  带TenantId
        ProcessInstance pi = omcActivitiService.startProcessInstanceByKeyAndTenantId(MedicConstant.PROCESS_KEY_MEDIC_RECORD,
                recordVariables, loginAuthDto.getGroupId());
        // 根据流程实例Id查询任务
        Task recordTask = taskService.createTaskQuery().processInstanceId(pi.getProcessInstanceId()).singleResult();

        // 获取流程实例id
        String processInstanceId = recordTask.getProcessInstanceId();
        // 设置用户id()
        Authentication.setAuthenticatedUserId(loginAuthDto.getUserName() + "[班长]");
        // 添加批注信息
        taskService.addComment(recordTask.getId(), processInstanceId, MedicConstant.MEDIC_RECORD_COMMENT_APPLY);
        //
        //taskService.complete(recordTask.getId());

        omcMedicRecord.setProcessInstanceId(pi.getProcessInstanceId());
        omcMedicRecord.setState(MedicConstant.MEDIC_RECORD_STATE_APPLY);
        omcMedicRecord.setUpdateInfo(loginAuthDto);

        return omcMedicRecordMapper.insertSelective(omcMedicRecord);
    }

    /**
     * medic record feed delay by process instance id
     *
     * @param processInstanceId the process instance id
     * @return the int.
     */
    @Override
    public Integer feedDelayByProcessInstanceId(String processInstanceId) {

        return updateStatByProcessInstanceId(MedicConstant.MEDIC_RECORD_STATE_DELAY_FEED, processInstanceId);
    }

    /**
     * medic record feed delay by process instance id
     *
     * @param processInstanceId the process instance id
     * @return the int.
     */
    @Override
    public Integer nursingConfirmDelayByProcessInstanceId(String processInstanceId) {

        return updateStatByProcessInstanceId(MedicConstant.MEDIC_RECORD_STATE_DELAY_NURSING_CONFIRM, processInstanceId);
    }

    /**
     * medic record monitor confirm delay by process instance id
     *
     * @param processInstanceId the process instance id
     * @return the int.
     */
    @Override
    public Integer monitorConfirmDelayByProcessInstanceId(String processInstanceId) {

        return updateStatByProcessInstanceId(MedicConstant.MEDIC_RECORD_STATE_DELAY_MONITOR_CONFIRM, processInstanceId);
    }

    /**
     * medic record apply feed by process instance id
     *
     * @param processInstanceId the process instance id
     * @return the int.
     */
    @Override
    public Integer applyFeedByProcessInstanceId(String processInstanceId) {

        return updateStatByProcessInstanceId(MedicConstant.MEDIC_RECORD_STATE_APPLY, processInstanceId);
    }

    @Override
    public List<MedicRecordVo> queryOldmanMedicException(Long oldmanId, String beginDate, String endDate) {
        return omcMedicRecordMapper.queryOldmanMedicException(oldmanId,beginDate, endDate);
    }

    /**
     * query medic record list by plan id and begin date
     *
     * @param medicPlanId   the medic plan id
     * @param beginDate     the begin date
     *
     * @return  the list
     */
    @Override
    public List<OmcMedicRecord> queryMedicRecordListByPlanIdAndBeginDate(Long medicPlanId, String beginDate) {

        return omcMedicRecordMapper.queryMedicRecordListByPlanIdAndBeginDate(medicPlanId, beginDate);
    }

    /**
     * update medic record state by process instance id
     *
     * @param state             the medic record state
     * @param processInstanceId the process instance id
     *
     * @return  the int
     */
    private Integer updateStatByProcessInstanceId(int state, String processInstanceId) {

        Example example = new Example(OmcOrder.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("processInstanceId", processInstanceId);

        OmcMedicRecord omcMedicRecord = new OmcMedicRecord();
        omcMedicRecord.setState(state);
        omcMedicRecord.setUpdateTime(new Date());

        return omcMedicRecordMapper.updateByExampleSelective(omcMedicRecord, example);
    }
}
